package clustering.streamming;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import preprocess.XMLDoc;
import similarity.Similarity;

public class Cluster
{
    private List<String> context;
    private XMLDoc       center;
    private int          level;

    public static Cluster createCluster(XMLDoc doc)
    {
        Cluster result = new Cluster();
        result.context = new LinkedList<String>();
        result.context.add(doc.getDocID());
        result.center = doc;
        result.level = 0;
        return result;
    }

    public static Cluster createCluster(List<XMLDoc> list, XMLDoc center)
    {
        Cluster result = new Cluster();
        result.context = new LinkedList<String>();
        for (XMLDoc doc : list)
            result.context.add(doc.getDocID());
        result.center = center;
        result.level = 1;
        return result;
    }

    public static Cluster combine(Collection<Cluster> clusters,
            Similarity similarity)
    {
        Cluster result = new Cluster();
        result.context = new LinkedList<String>();
        for (Cluster clu : clusters)
        {
            result.context.addAll(clu.context);
            result.level = clu.level + 1;
        }
        // TODO calculate the center XMLDoc
        result.center = getCenter(clusters, similarity);
        return result;
    }

    private static XMLDoc getCenter(Collection<Cluster> list,
            Similarity similarity)
    {
        XMLDoc result = null;
        double distanceSum = Double.MAX_VALUE;
        for (Cluster center : list)
        {
            double sum = 0;
            double centerWeight = center.getWeight();
            XMLDoc centerDoc = center.getCenter();
            for (Cluster clu : list)
            {
                double distance = 1 - similarity.calcSimilarity(centerDoc, clu
                        .getCenter());
                distance *= (centerWeight * clu.getWeight());
                sum += distance * distance;
            }
            if (sum < distanceSum)
            {
                distanceSum = sum;
                result = centerDoc;
            }
        }
        return result;
    }

    private Cluster()
    {
    }

    /**
     * @return the context
     */
    public List<String> getContext()
    {
        return context;
    }

    /**
     * @return the center
     */
    public XMLDoc getCenter()
    {
        return center;
    }

    /**
     * @return the level
     */
    public int getLevel()
    {
        return level;
    }

    /**
     * @return the weight of the current cluster
     */
    public int getWeight()
    {
        return context.size();
    }

    public String toString()
    {
        return center.toString() + ":" + getWeight();
    }
}
